#include "socketServer.h"

#include <QTcpServer>
#include <QTcpSocket>
#include <QDebug>

#include "pfunc_qt.h"
#include "confdeal.h"

SocketServer::SocketServer()
{
	init();
}

SocketServer::~SocketServer()
{
	stopListen();
}

void SocketServer::init()
{
    ConfDeal *ptr_ConfDeal = ConfDeal::getInstance();
    listenPort = ptr_ConfDeal->getListenPort();
    m_pSocket = NULL;
	m_pServer = new QTcpServer(this);
	connect(m_pServer, SIGNAL(newConnection()), this, SLOT(newConnectionSlot()));
	isListen();
}

bool SocketServer::isListen()
{
	if (!m_pServer->isListening())
	{
        if (!m_pServer->listen(QHostAddress::Any, listenPort))
		{
			return false;
		}
	}
    qInfo() << QString("listen port(%1) now!").arg(listenPort);
	return true;
}

void SocketServer::stopListen()
{
	if (m_pServer->isListening())
	{
		m_pServer->close();
	}
}

void SocketServer::newConnectionSlot()
{
	m_pSocket = m_pServer->nextPendingConnection();
    if(NULL==m_pSocket)
        return;
    connect(m_pSocket, SIGNAL(disconnected()), m_pSocket, SLOT(deleteLater()));
	connect(m_pSocket, SIGNAL(readyRead()),this, SLOT(dataReceived()));
    connect(m_pSocket,SIGNAL(destroyed()),this,SLOT(disObj()));
    if(!m_pSocket->peerAddress().isNull()){
        qInfo() << QString("new connect(%1,%2) now!")
               .arg(m_pSocket->peerAddress().toString())
               .arg(m_pSocket->peerPort());
    }else{
        qInfo() << QString("new connect now!");
    }
}

void SocketServer::disObj()
{
    if(m_pSocket!=NULL){
        m_pSocket=NULL;
    }
}

void SocketServer::sendItem(int id,int val)
{
    if(NULL==m_pSocket)
        return;
    int idx = 0;
    unsigned char buf[512] = {0};
    buf[idx++]=id<100?0XF3:0XF4;
    //信息长度
    buf[idx++] = 0xf0;		//1-Len_L
    buf[idx++] = 0xf0;		//2-Len_H
    //pid
    buf[idx++] = (unsigned char)(id & 0xff);
    buf[idx++] = (unsigned char)((id >> 8) & 0xff);
    buf[idx++] = (unsigned char)((id >> 16) & 0xff);
    buf[idx++] = (unsigned char)((id >> 24) & 0xff);
    //val
    buf[idx++] = (unsigned char)(val & 0xff);
    buf[idx++] = (unsigned char)((val >> 8) & 0xff);
    buf[idx++] = (unsigned char)((val >> 16) & 0xff);
    buf[idx++] = (unsigned char)((val >> 24) & 0xff);

    buf[1] = static_cast<unsigned char>(idx & 0xff);
    buf[2] = static_cast<unsigned char>((idx >> 8) & 0xff);
    unsigned char m_end = 0xFF;
    memcpy(buf+idx,&m_end,1);
    idx++;

    unsigned char _buf[256]={0};
    int nLen = code(buf, idx, _buf);
    //QByteArray _wd((const char*)_buf,nLen);
//    for(int j=0; j<nLen;j++){
//        printf("%02X",_buf[j]);
//    }
//    printf("\n");
    m_pSocket->write((const char*)_buf, nLen);
    m_pSocket->flush();
}

void SocketServer::dataReceived()
{
	// qDebug() <<"read data now!\n";
    if(NULL==m_pSocket)
        return;
    if(!m_pSocket->isValid())
        return;
	while(m_pSocket->bytesAvailable())
	{
		QByteArray vTemp;
		vTemp = m_pSocket->readAll();

		unsigned char * pBuf = new unsigned char[vTemp.length()];
        /*int nLen = */uncode((const unsigned char *)vTemp.data(), vTemp.length(), pBuf);
		unsigned char type = pBuf[0];
		int idx = 1;
		switch (type)
		{
        case 0XF3:case 0XF4:
		{
            int hlen = ((pBuf[idx++]) << 8);
            int len = (pBuf[idx++] + (hlen));
			int pID = 0;
			pID += pBuf[idx++];
			pID += (pBuf[idx++] << 8);
			pID += (pBuf[idx++] << 16);
			pID += (pBuf[idx++] << 24);

            int Value = 0;
            Value += pBuf[idx++];
            Value += (pBuf[idx++] << 8);
            Value += (pBuf[idx++] << 16);
            Value += (pBuf[idx++] << 24);
            //
			unsigned char endflag = pBuf[idx++];
            if(0XFF!=endflag){
                qDebug() << QString("dataReceived error end,len(%1)").arg(len+1);
            }
            emit SetItem(pID,Value);
		}
			break;
		default:
			break;
		}
		delete [] pBuf;
	}
}

int SocketServer::code(const unsigned char *buff, const int len, unsigned char *outbuf)
{
    char ch = 0;
    int nLen = 0;
    unsigned char * buf = (unsigned char *)buff;
    for (int i = 0; i < len; i++, nLen++)
    {
        ch = buf[i];
        if ((buf[i] | 0x0f) == 0xff && i > 0 && i < (len - 1))
        {
            *outbuf++ = 0xf0 & buf[i];
            *outbuf++ = 0x0f & buf[i];
            nLen += 1;
        }
        else {
            *outbuf++ = ch;
        }
    }
    return nLen;
}

int SocketServer::uncode(const unsigned char *buff, int len, unsigned char *outbuf)
{
	char ch = 0;
	int nLen = 0;
	unsigned char * buf = (unsigned char *)buff;
	for (int i = 0; i < len; i++, nLen++)
	{
		ch = buf[i];
		if (buf[i] == 0xf0)
		{
#ifdef _DEBUG
			if (i > len - 2)
				printf("Error!\r\n");
			if (buf[i + 1] > 0x0f)
				printf("Error!\r\n");
#endif
			ch = 0xf0 | buf[++i];
		}
		*outbuf++ = ch;
	}
	return nLen;
};
